//主程序
#include<stdio.h>
#define MAX 1024


//程序1
//指针类实现strcpy
void test1()
{
	char str1[MAX];
	printf("请输入要拷贝到str2的字符串：");
	fgets(str1, MAX, stdin);

	char str2[MAX];

	char* targets1 = str1;
	char* targets2 = str2;

	printf("-----拷贝程序开始-------");
	while ((*targets2++ = *targets1++) != '\0');

	printf("现在,str1的内容是：%s\n", str1);
	printf("str2的内容是：%s", str2);


}

//程序2
//strcpy实现拷贝
#include<string.h>
void test2()
{

	/*
	strcpy函数概要：
	strcpy 函数用于拷贝字符串，包含最后的结束符 '\0'。
	为了避免溢出，必须确保用于存放的数组长度足以容纳待拷贝的字符串（注意：长度需要包含结束符 '\0'）。
	源字符串和目标数组的位置不应该重叠。


	函数原型：
		#include <string.h>
		...
		char *strcpy(char *dest, const char *src);

	参数解析：
		参数				含义
		dest			指向用于存放字符串的目标数组
		src				指向待拷贝的源字符串
	*/
	char str1[MAX];
	printf("请输入要拷贝的字符串到str2：");
	fgets(str1, MAX, stdin);


	char str2[MAX];
	strcpy(str2, str1);//strcpy(目标待拷贝字符数组，源字符数组)
	printf("--------开始拷贝--------\n");
	printf("现在str2的拷贝结果为：%s", str2);

}

//程序3
//利用指针实现strcpy功能进行对用户选定范围进行拷贝(包含中英文混写)

void test3()
{
	char str1[MAX];
	char* targets1 = str1;
	printf("请输入一段字符串：");
	fgets(str1, MAX, stdin);


	char str2[MAX];
	char* targets2 = str2;

	int n;//初始化拷贝计数器
	printf("请输入要拷贝的字符个数：");
	scanf("%d", &n);

	char ch;
	while (n--)
	{
		ch = *targets2++ = *targets1++;//执行拷贝代码，将*targets2++ = *targets1++(利用while循环使得tragets++，指向元素的下一个元素)
		if (ch == '\0')
		{
			break;
		}
		if ((int)ch < 0)//中文字符判断
		{
			*targets2++ = *targets1++;
			//可能这里会看不懂，根据运算符优先级，先运算++,即*（targets++），先移动指针所指位置，再取值;
			//中文字符在VS数组中占据三个字节，所以我们需要进行对数组的移动才能进行取值
		}

	}

	*targets2 = '\0';
	printf("输出结果为：%s\n", str2);




}

//程序4
//利用strcpy实现拷贝,同时过滤前N个字符拷贝(原来是本意是使用strcpy进行程序3拷贝的，发现出现了错误，这个错误可以成为这个例子)
void test4()
{

	int n;
	char str1[MAX];
	char* targets1 = str1;


	printf("请输入一段字符串：");
	fgets(str1, MAX, stdin);

	printf("请输入要过滤的字符个数：");
	scanf("%d", &n);


	char str2[MAX];
	char* targets2 = str2;

	char ch;
	while (n--)
	{
		ch = *targets1++;
		if ((int)ch < 0)//在此出*targets1移动到了str1[1]位置
		{
			*targets2++ = *targets1++;//中文检测
		}
		strcpy(targets2, targets1);
		/*
			所以从此处看targets2读取的是原来（targets1 + 1）位置，也就是从str1[1]开始读取并进行拷贝
			即stracpy(targets2,targets1+1)。这样的写法出现错误，因为 ch = *targets1++，是导致了指针移动的关键
			若强行使用strcpy拷贝程序过于复杂,建议使用指针模拟实现<程序3>or使用strncpy实现<程序5>
		*/
	}

	printf("拷贝结果:%s", str2);


}

//程序5
//利用strncpy对选中字符进行拷贝
//strncpy使用优势可以定向选择要拷贝的字符数；

//strncpy函数原型
/*	
	#include <string.h>
	...
	char* strncpy(char* dest, const char* src, size_t n);
*/

//	参数					含义
//	desk				指向存放字符串的目标数组		
//	src					指向待拷贝的源字符串
//	n					指定拷贝的最大长度

/*和 strcpy 函数一样，strncpy(dest, src, n) 函数将拷贝源字符串的 n 个字符到目标数组中。
如果源字符串的长度小于 n，那么就用 '\0' 填充额外的空间。
如果源字符串的长度大于或等于 n，那么只有 n 个字符被拷贝到目标数组中（注意：这样的话将不会以结束符 '\0' 结尾,也就是需要手动添加'\0'）。*/
void test5()
{
	int n;
	printf("请输入要拷贝的字符个数：");
	scanf("%d", &n);


	char str1[MAX];
	printf("请输入一段字符串：");
	scanf("%s", str1);

	if (n > strlen(str1)) n = strlen(str1);//防止n设置过大，导致溢出

	char str2[MAX];



	str2[n] = '\0';//使用strncpy函数的时候，strncpy在末尾出不会自动添加'\0',放置数组溢出必须加'\0'

	strncpy(str2, str1, n);
	printf("%s", str2);
}

int main()
{
	/*
		索引					功能
		test1				指针类实现strcpy
		test2				strcpy实现拷贝
		test3				利用指针实现strcpy功能进行对用户选定范围进行拷贝（包括中英文混写）
		test4				利用strcpy实现拷贝,同时过滤前N个字符拷贝（重点关注）
		test5				利用strncpy函数对用户选定范围进行拷贝			
	*/

	test5();
	return 0;
}
